<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/* ****************************************************************************
  NAIYUMIE KING WANG JJANG Front End Developer <naiyumie@gmail.com>
  FileType:CRLF, Encording:UTF-8, Tab&Space:4/4
  ------------------------------------------------------------------------
  밸리데이션

	1) filtering to specialchars
	   1-1) ' >> ‘’
	   1-2) " >> “”
	   1-3) htmlspecialchars

    2) distinct to prefix
        *---------------------------------------------------------------------------*
        | prefix | transaction | validation                                         |
        |---------------------------------------------------------------------------|
        | 'pk_'  | C           | null,maxlen(10),number                             |
        |        | UD          | notnull,maxlen(10),number                          |
        |---------------------------------------------------------------------------|
        | 'no_'  | CU          | notnull,maxlen(10),number                          |
        |---------------------------------------------------------------------------|
        | 'fk_'  | CU          | number,notnull,maxlen(10)                          |
        |---------------------------------------------------------------------------|
        | 'uq_'  | CU          | notnull,maxlen(255)                                |
        |---------------------------------------------------------------------------|
        | 'pw_'  | CU          | notnull,maxlen(255)                                |
        |---------------------------------------------------------------------------|
        | 'dt_'  | CU          | notnull,maxlen(10),reg(0000-00-00)                 |
        |---------------------------------------------------------------------------|
        | 'tm_'  | CU          | notnull,maxlen(8),reg(00:00:00)                    |
        |---------------------------------------------------------------------------|
        | 'fg_'  | CU          | notnull,alpanumeric, enum(a|b|c) enum(y|n)         |
        |---------------------------------------------------------------------------|
        | 'st_'  | CU          | n/a,maxlen(255)                                    |
        |---------------------------------------------------------------------------|
        | 'tx_'  | CU          | n/a                                                |
        +---------------------------------------------------------------------------+

	3) vStatArray prototype
		$this->vStatArray = array(
			'key' => array(
				'value' => '',
				'basicValidation' => array(
					'isBlank' => 'pass'
				),
	            'extendValidation' => array(
	                'isIdPw'  => 'pass',
	                'isMatch' => 'dont'
	            )
			)
		);
	    >> delete value for security

   4) _setVStatFailedResultArray
			[pk_uid] => Array
	        (
	            [value] => 123456789
	            [basicValidation] => Array
	                (
	                    [isBlank] => pass
	                    [isRangeLTECheck] => pass
	                    [isNumericCheck] => pass
	                )

	        )
**************************************************************************** */

class Nvalidation {

	private $CI;
	var $vStatArray = array();
	var $vStatFailedResultArray = array();

	public function __construct() {
    	$this->CI =& get_instance();
    }

	/***************************************************
	 * validtation  phase
	 ***************************************************/

	# basicValidation 기본 밸리데이션 - DB 스키마에 따라 결정
	function basicValidation($argArray=array()){
		foreach($argArray['validationValueArray'] as $key=>$val){
			$this->vStatArray[$key]['value'] = $val;
			if(strpos($key, 'pk_') !== FALSE){
				if(@$argArray['mode'] == 'update'){
					$this->isBlankCheck($this->vStatArray, $key, $val);
				}
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 10);
				$this->isNumericCheck($this->vStatArray, $key, $val);
			}

			if(strpos($key, 'no_') !== FALSE || strpos($key, 'fk_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 10);
				$this->isNumericCheck($this->vStatArray, $key, $val);
			}

			if(strpos($key, 'pw_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 255);
			}

			if(strpos($key, 'uq_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 255);
				if(isset($argArray['uq_']) !== TRUE){
					$this->isUniqueCheck($this->vStatArray, $key, $val,
						array(
							'uq_tableName' => $argArray['uq_tableName'],
							'columnPk' => @$argArray['validationValueArray']['pk_uid'],
							'columnName' => $key,
							'columnValue' => $val
						)
					);
				}
			}

			if(strpos($key, 'dt_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 10);
				$this->isDateCheck($this->vStatArray, $key, $val);
			}

			if(strpos($key, 'tm_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 8);
				$this->isTimeCheck($this->vStatArray, $key, $val);
			}

			#checkbox 는 enum(y|n) 만 된다.
			if(strpos($key, 'fg_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isEnumCheck($this->vStatArray, $key, $val, array('fg_tableName' => $argArray['fg_tableName'], 'columnName' => $key));
			}

			if(strpos($key, 'st_') !== FALSE){
				$this->isBlankCheck($this->vStatArray, $key, $val);
				$this->isRangeLTECheck($this->vStatArray, $key, $val, 255);
			}
		}

		return $this->_setVStatFailedResultArray();
	}


	# extendValidation 확장 밸리데이션 - 기타 확장사항 컨트롤러의 코드에 따라 결정
	function extendValidation($argArray=array()){
		foreach($argArray['validationValueArray'] as $key=>$val){
			if(isset($argArray['extendValidationRuleArray'][$key]) && is_array($argArray['extendValidationRuleArray'][$key])){
				foreach($argArray['extendValidationRuleArray'][$key] as $key2=>$val2){
					#maxlen(23)
					if(preg_match('/(maxlen)(\((\d{2,3})\))/', $val2, $match)){
						$matchnum = @$match[3];
						$this->isRangeLTECheck($this->vStatArray, $key, $val, $matchnum);
					}
					#important(y)
					if(preg_match('/(important)((\((.*?){1})\))/', $val2, $match)){
						$matchnum = @$match[4];
						$this->isEqualCheck($this->vStatArray, $key, $val, $matchnum);
					}
					#email
					if(preg_match('/(email)/', $val2)){
						$this->isEmailCheck($this->vStatArray, $key, $val);
					}
					#equalto(___member_pw)
					if(preg_match('/(equalto)((\((.*?))\))/', $val2, $match)){
						$matchId = @$match[4];
						$matchIdChecker = $this->vStatArray[$matchId]['value'];
						$this->vStatArray[$matchId]['basicValidation']['isEqualCheck'] = ($this->isEqual($val, $matchIdChecker)) ? 'pass':'dont';
					}

				}
			}
		}

		return $this->_setVStatFailedResultArray();
	}

	# 리턴하는 값
	function _setVStatFailedResultArray(){
		$i=0;
		# vStatFailedResultArray에 값을 넣는다.
		foreach($this->vStatArray as $columnKey => $valArray){
			if(isset($valArray['basicValidation'])){
				foreach ($valArray['basicValidation'] as $key => $val) {
					if($val != 'pass'){
						#develop for debugging
						//if(false)
						{
							$i++;
							$this->vStatFailedResultArray[$i][] = array('columnName'=>$columnKey);
							$this->vStatFailedResultArray[$i][] = array('validationType'=>$key);
						}

						#when debug end
						if(false)
						{
							$this->vStatFailedResultArray[] = array('columnName'=>$this->CI->nurl->encrypt($columnKey));
						}

					}
				}
			}
		}

		# $this>vStatFailedResultArray가 0보다 크다면 dont가 존재하므로 validation에 통과하지 못한다.
		if(sizeof($this->vStatFailedResultArray) > 0){
			return FALSE;
		} else {
			return TRUE;
		}
	}

	/***************************************************
	 * check candy wrap method
	 ***************************************************/
	function isUniqueCheck(&$vStatArray, $arg01, $arg02, $argArray01 = array()){
		$vStatArray[$arg01]['basicValidation']['isUniqueCheck'] = ($this->CI->GlobalM->isUnique($argArray01)) ? 'pass' : 'dont';
	}

	function isBlankCheck(&$vStatArray, $arg01, $arg02){
		$vStatArray[$arg01]['basicValidation']['isBlankCheck'] = (!$this->isBlank($arg02)) ? 'pass' : 'dont';
	}

	function isRangeLTECheck(&$vStatArray, $arg01, $arg02, $len){
		$vStatArray[$arg01]['basicValidation']['isRangeLTECheck'] = ($this->isRangeLTE($arg02, $len)) ? 'pass' : 'dont';
	}

	function isNumericCheck(&$vStatArray, $arg01, $arg02){
		$vStatArray[$arg01]['basicValidation']['isNumericCheck'] = (!$this->isNumeric($arg02)) ? 'pass' : 'dont';
	}

	function isDateCheck(&$vStatArray, $arg01, $arg02){
		$vStatArray[$arg01]['basicValidation']['isDateCheck'] = ( $this->isDate($arg02)) ? 'pass' : 'dont';
	}

	function isTimeCheck(&$vStatArray, $arg01, $arg02){
		$vStatArray[$arg01]['basicValidation']['isTimeCheck'] = ( $this->isTime($arg02)) ? 'pass' : 'dont';
	}

	function isEnumCheck(&$vStatArray, $arg01, $arg02, $argArray01 = array()){
		$enumSet = $this->CI->GlobalM->getEnumColumn($argArray01);
		if(in_array($arg02,$enumSet)){
			$flag = 'pass';
		} else {
			$flag = 'dont';
		}
		$vStatArray[$arg01]['basicValidation']['isEnumSetCheck'] = $flag;
	}

	function isEqualCheck(&$vStatArray, $arg01, $arg02, $len){
		$vStatArray[$arg01]['basicValidation']['isEqualCheck'] = ($this->isEqual($arg02, $len)) ? 'pass' : 'dont';
	}

	function isEmailCheck(&$vStatArray, $arg01, $arg02){
		$vStatArray[$arg01]['basicValidation']['isEmailCheck'] = ($this->isEmail($arg02)) ? 'pass' : 'dont';
	}

	/***************************************************
	 * basic data type Validation
	 * 기본 자료형과 기본 함수에 근접한 것
	 * 인자는 모두 arg01
	 ***************************************************/

		# 빈문자열 인지 검사
		public function isBlank($arg01) {
			$temp=str_replace("　","",$arg01);
			$temp=strip_tags($temp);
			$temp=str_replace(" ","",$temp);
			$temp=str_replace(" ","",$temp);
			if(!preg_match("|[^[:space:]]|",$temp)) {
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 숫자로 이루어졌는지 검사 -- 값이없을경우는 isBlank체크
		public function isNumeric($arg01) {
			if(preg_match("|[^0-9]|",$arg01)) {
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 숫자, 영문자로 이루어져 있는지 검사
		public function isAlphaNumeric($arg01) {
			if(eregi("[^0-9a-zA-Z_]",$arg01)){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 아이디 패스워드로 유용한 값인가. 6~32자리
		public function isIdPw($arg01) {
			$pattern = "/^[a-z0-9_!#$%^&*()?+=\/]{6,32}$/";
			if(preg_match($pattern, $arg01)){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# varchar에 입력 할 수 있는지 리턴
		public function isVarchar($arg01) {
			if(mb_strlen($arg01, 'utf-8') < 255){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 두 값이 일치할 경우.
		public function isEqual($arg01, $arg02) {
			if(strcmp($arg01, $arg02) == 0){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 문자열이 포함 되어있는지 검사
		public function isHasString($heystack, $needle){
			if(strpos($heystack,$needle) !== FALSE){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 문자열 길이가  같은지검사
		public function isRangeMatch($arg01, $arg02, $len){
			if(strncmp($arg01,$arg02,$len) != TRUE){
				#echo "[isRange>>false]";
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 7이상                    X ≥ 7; X is greater than or equal to 7.
		# 7초과                    X > 7; X is greater than 7.
		# 7이하                    X ≤ 7: X is less than or equal to 7.
		# 7미만                    X < 7; X is less than 7.
		# -- 값이없을경우는 isBlank체크
		public function isRangeGTE($arg01, $len){
			if(strlen($arg01) >= $len){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		public function isRangeGT($arg01, $len){
			if(strlen($arg01) > $len){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		public function isRangeLTE($arg01, $len){
			if(strlen($arg01) <= $len){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		public function isRangeLT($arg01, $len){
			if(strlen($arg01) < $len){
				return TRUE;
			} else {
				return FALSE;
			}
		}

	/***************************************************
	 * advanced logical Validation
	 * 주민등록번호, 셀폰, 시간 같은 특이 타입
	 ***************************************************/

	 	# 날짜 형식 검사
	 	public function isDate($arg01){
	 		if(preg_match("/([0-9]{4})-([0-9]{1,2})-([0-9]{1,2})/", $arg01) && (preg_match('/^(\d{4})-(\d{2})-(\d{2})$/',$arg01,$match) && checkdate($match[2],$match[3],$match[1]))){
				return TRUE;
	 		} else {
	 			return FALSE;
	 		}
	 	}

	 	# 시간 형식 검사
	 	public function isTime($arg01){
	 		if(preg_match("/([0-9]{1,2}):([0-9]{1,2}):([0-9]{1,2})/", $arg01) ){
				return TRUE;
	 		} else {
	 			return FALSE;
	 		}
	 	}

		# 셀폰 검사
		public function isCellPhone($arg01, $has_dash = FALSE) {
			$pattern = "/([0]{1}[1]{1}[016789]{1})+([0-9]{3,4})+([0-9]{4})/";
			if($has_dash == TRUE){
				$arg01 = preg_replace("/-/i", "", $arg01);
			}
			if(
				strlen(preg_replace("/-/i", "", $arg01)) <= 11 &&
				strlen(preg_replace("/-/i", "", $arg01)) >= 10){
				//echo "match count";
				if(preg_match($pattern, $arg01)){
					return TRUE;
				} else {
					return FALSE;
				}
			} else {
				return FALSE;
			}
		}

		# 이메일 일치 검사
		public function isEmail($arg01) {
			$pattern = "/^[_\.0-9a-zA-Z-]+@([0-9a-zA-Z][0-9a-zA-Z-]+\.)+[a-zA-Z]{2,6}$/i";
			if(preg_match($pattern, $arg01)){
				return TRUE;
			} else {
				return FALSE;
			}
		}

		# 주민번호 검사
		public function isResidentRegistrationNumber($arg01) {
			$weight = '234567892345'; # 자리수 weight 지정
			$len = strlen($arg01);
			$sum = 0;
			if ($len <> 13) {
				return false;
			}
			for ($i = 0; $i < 12; $i++) {
				$sum = $sum + (substr($arg01, $i, 1) * substr($weight, $i, 1));
			}

			$rst = $sum%11;
			$result = 11 - $rst;
			if ($result == 10) {
				$result = 0;
			} else if ($result == 11) {
				$result = 1;
			}

			$jumin = substr($arg01, 12, 1);
			if ($result <> $jumin) {
				return false;
			}
			return true;
		}

		# 한글검사
		public function isHangul($arg01) {
			if (strlen($arg01) != 2) return FALSE;
			$i = ord ($arg01[0]);
			$j = ord ($arg01[1]);
			if ($i < 0x81 || $i > 0xC8 || $j > 0xFE || ($j >= 0x00 && $j <= 0x40) || ($j >= 0x5B && $j <= 0x60) || ($j >= 0x7B && $j <= 0x80) || ($j >= 0x00 && $j <= 0x40) || (($i >= 0xA1 && $i <= 0xAF) && ($j >= 0xA1 && $j <= 0xFE)) || ($i == 0xC6 && ($j >= 0x53 && $j <= 0xA0)) || ($i >= 0xC7 && ($j >= 0x41 && $j <= 0xA0))) return FALSE;
			else return TRUE;
		}

		# URL 주소가 올바른지 검사
		public function isUrl($arg01) {
			if(eregi("^http://([a-z0-9_-./~@?=&-#{5,}]+)", $arg01)) return TRUE;
			else return FALSE;
		}

	/***************************************************
	 * encrypt to decodes
	 * POST로 받은 암호화 된 값을 필터하고 복호화 하여 리턴
	 * db prefix에 의해 결정 된다.
	 * 라이브러리 참조 : https://github.com/mdp/gibberish-aes
	 ***************************************************/
	public function postAesDecodes(){
		$req = $_POST;
		foreach($req as $key=>$val){
			if($key == 'GAesKey'){
				$reqN['GAesKey'] = $val;
			} else {
				$reqN[$this->CI->nurl->decrypt($key)] = $val;
			}
		}
		$filteringPrefixArray = array(
			'pk_',
			'uq_',
			'st_',
			'pw_',
			'fg_',
			'no_',
			'fk_',
			'dt_',
			'tm_',
			'tx_',
			'___',
			'ck_'
		);
		$filteringTarget = array();
		foreach ($reqN as $key => $value) {
			if(in_array(substr($key,0,3), $filteringPrefixArray)){
				array_push($filteringTarget, $key);
			}
		}
		$retVal = array();
		foreach ($filteringTarget as $key => $value) {
			if(strpos($value, 'pk_') !== FALSE){
				$retVal[$value] = $this->CI->gibberishaes->dec($reqN[$value], $this->CI->config->item('aes_key'));
			} else {
				$retVal[$value] = $this->CI->gibberishaes->dec($reqN[$value], $reqN['GAesKey']);
			}
		}
		return $retVal;
	}
}
/* End of file */